﻿
Partial Class WebForm_ManageRole_SearchRoleProgramMappingByRole
    Inherits System.Web.UI.UserControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Me.Visible = False

        If Not IsPostBack Then
            Me.BindDDLProgramGroup()
            RaiseEvent Loaded(Me, New EventArgs)
        End If
    End Sub

    Protected Sub chkAll_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim chkAll As CheckBox = TryCast(sender, CheckBox)
        Dim cellIndex = Me.gv.HeaderRow.Cells.GetCellIndex(chkAll.Parent)

        'For Each row As GridViewRow In Me.gv.Rows
        '    Dim chkAuth As CheckBox = TryCast(row.Cells(cellIndex).Controls(1), CheckBox)

        '    chkAuth.Checked = chkAll.Checked
        'Next

        'Me.Show()

        Me.AddAllRoleAuthMapping(chkAll)
        Me.Show(Me.RoleID)
    End Sub

    Protected Sub chk_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim chk As CheckBox = TryCast(sender, CheckBox)

        Me.AddRoleAuthMapping(chk)
        Me.Show(Me.RoleID)
    End Sub

    Protected Sub gv_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles gv.PageIndexChanging
        Me.gv.PageIndex = e.NewPageIndex
        Me.Show(Me.RoleID)
    End Sub

    Protected Sub gv_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gv.RowCommand
        If e.CommandName = "lknProgramName" Then
            Dim row As GridViewRow = TryCast(TryCast(e.CommandSource, Control).NamingContainer, GridViewRow)
            Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)
            'Me.SearchRoleProgramColumnMappingByRole1.Show(Me.RoleID, key("ProgramID"))
        End If

        Me.Show()
    End Sub

    Protected Sub gv_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gv.RowDataBound
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim key As DataKey = Me.gv.DataKeys(e.Row.RowIndex)

            '表單群組
            If TypeOf key("Parent") Is DBNull OrElse key("Parent") = 0 Then
                TryCast(e.Row.FindControl("lknProgramName"), LinkButton).Font.Bold = True

                'For Each auth As String In Me.authList

                '    If auth <> "Query" Then
                '        Dim chkAuth As CheckBox = TryCast(e.Row.FindControl("chk" + auth), CheckBox)
                '        chkAuth.Enabled = False
                '    End If
                'Next

            End If

            '檢查是否可設定欄位權限
            'If TypeOf key("TableName") Is DBNull Then
            '    TryCast(e.Row.FindControl("lknProgramName"), LinkButton).Enabled = False
            'End If
        End If
    End Sub

    'Protected Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
    '    Me.AddRoleAuthMapping()
    '    Me.Show(Me.RoleID)
    'End Sub

    Protected Sub ddlProgramGroup_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlProgramGroup.SelectedIndexChanged
        Me.BindGV()
        Me.Show()
    End Sub
End Class

Partial Class WebForm_ManageRole_SearchRoleProgramMappingByRole
    Private authList() As String = {"Query", "Add", "Edit", "Delete", "Print", "Admin"}

    ''' <summary>
    ''' 僅顯示，不重載資料
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Show()
        Me.mpSearch.Show()
        Me.Visible = True
    End Sub

    Private Function FindAuth(ByVal searchText As String) As String
        For Each auth As String In Me.authList
            If searchText.Contains(auth) Then
                Return auth
            End If
        Next
    End Function

    ''' <summary>
    ''' 顯示且重載資料
    ''' </summary>
    ''' <param name="roleID"></param>
    ''' <remarks></remarks>
    Public Sub Show(ByVal roleID As String)
        Me.RoleID = roleID
        Me.BindData()
        Me.BindGV()

        Me.mpSearch.Show()
        Me.Visible = True
    End Sub

    Private Sub BindData()
        Me.btnSave.Visible = False
    End Sub

    Private Sub BindDDLProgramGroup()
        Dim dat As New clsData
        Dim sql As New MyStringBuilder
        Dim dt As Data.DataTable

        'sql.AppendFormat("select p.* ")
        'sql.AppendFormat("from Program p ")
        'sql.AppendFormat("where p.Parent is null or p.Parent = 0 ")
        sql.AppendFormat("select p.ProgramID, p.ProgramName ")
        sql.AppendFormat("from ( ")
        sql.AppendFormat("select ProgramGroupID = ProgramID from Program p ")
        sql.AppendFormat("where p.Parent=0 or p.ProgramID = 0 ")
        sql.AppendFormat("union select pg.ProgramGroupID ")
        sql.AppendFormat("from ProgramGroup pg ) pg ")
        sql.AppendFormat("inner join Program p on pg.ProgramGroupID = p.ProgramID ")
        sql.AppendFormat("order by p.Parent, p.Sequence ")
        dt = dat.GetData(sql)

        Me.ddlProgramGroup.DataTextField = "ProgramName"
        Me.ddlProgramGroup.DataValueField = "ProgramID"
        Me.ddlProgramGroup.DataSource = dt
        Me.ddlProgramGroup.DataBind()
        Dim li As New ListItem

        li.Text = "----全部----"
        li.Value = ""
        Me.ddlProgramGroup.Items.Insert(0, li)
    End Sub

    Public Sub BindGV()
        Dim dat As New clsData
        Dim sql As New MyStringBuilder

        sql.Length = 0
        'sql.AppendFormat("select table1.* ")

        'sql.AppendFormat("from ( ")
        sql.AppendFormat("select distinct p.ProgramID, p.ProgramName, p.Parent, p.TableName ")
        'sql.AppendFormat(", null as ColumnName ")
        sql.AppendFormat(", 'Query' as QueryAccess ")
        sql.AppendFormat(", 'Add' as AddAccess ")
        sql.AppendFormat(", 'Edit' as EditAccess ")
        sql.AppendFormat(", 'Delete' as DeleteAccess ")
        sql.AppendFormat(", 'Print' as PrintAccess ")
        sql.AppendFormat(", 'Admin' AdminAccess ")
        sql.AppendFormat(", ProgramGroupID = p_parent.ProgramID ")
        sql.AppendFormat(", ProgramGroupName = p_parent.ProgramName ")
        sql.AppendFormat("from Program p ")
        sql.AppendFormat("left join Program p_parent on p.Parent = p_parent.ProgramID ")
        Dim parent As Integer = clsAuth.GetParentRoleID(Me.RoleID)

        If Me.RoleID <> parent Then
            '只能修改父群組有的權限 - 先排除父群組沒有的列
            sql.AppendFormat("inner join RoleProgramMapping rp on p.ProgramID = rp.ProgramID ")
            sql.AppendFormat("where p.Active = 'Y' ")
            sql.AppendFormat("and rp.RoleID = {0} ", parent)
        Else
            sql.AppendFormat("where p.Active = 'Y' ")
        End If

        If Me.ddlProgramGroup.SelectedIndex > 0 Then
            sql.AppendFormat("and p.Parent = {0} ", Me.ddlProgramGroup.SelectedValue)
        End If
        sql.AppendFormat(Me.gv.OrderBySQL)
        'sql.AppendFormat("order by Parent ")

        'sql.AppendFormat("union all ")
        'sql.AppendFormat("select p.ProgramID, p.ProgramName, c.name as ColumnName ")
        'sql.AppendFormat("from syscolumns c ")
        'sql.AppendFormat("inner join sysobjects o on c.id = o.id ")
        'sql.AppendFormat("inner join Program p on o.name = p.TableName ")
        'sql.AppendFormat(") table1 ")
        'sql.AppendFormat("order by ProgramName ")

        'sql.AppendFormat("where ru.RoleID = '{0}' ", Me.RoleID)
        Me.gv.DataSource = dat.GetData(sql)
        Me.gv.DataBind()

        If Me.RoleID <> parent Then

            '只能修改父群組有的權限 - 在畫面上停用父群組沒有的選項

            sql.Length = 0
            sql.AppendFormat("select ro.*, r.RoleName from RoleProgramMapping ro ")
            sql.AppendFormat("inner join Role r on ro.RoleID = r.RoleID ")
            sql.AppendFormat("where r.RoleID = '{0}' ", parent)

            Dim parentMappings As Data.DataTable = dat.GetData(sql.ToString, Nothing, Data.CommandType.Text, "dt").Tables(0)

            For Each row As GridViewRow In Me.gv.Rows
                Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)

                For Each auth As String In Me.authList

                    Dim chkAuth As CheckBox = TryCast(row.FindControl("chk" + auth), CheckBox)
                    Dim cellIndex = row.Cells.GetCellIndex(chkAuth.Parent)
                    Dim chkAll As CheckBox = TryCast(Me.gv.HeaderRow.Cells(cellIndex).Controls(1), CheckBox)

                    parentMappings.DefaultView.RowFilter = String.Format("ProgramID = '{0}' and AuthName = '{1}' ", key("ProgramID"), auth)

                    If parentMappings.DefaultView.Count = 0 Then
                        chkAuth.Visible = False
                        chkAuth.Checked = False
                    Else
                        'MyObj.ShowMessage(key("ProgramID"))
                    End If
                Next
            Next
        End If
        '
        '排除無法設定的權限
        '
        sql = New MyStringBuilder
        sql.AppendFormat("select * from ProgramAuthDefinition")

        Dim authDefinitions As Data.DataTable = dat.GetData(sql)

        For Each row As GridViewRow In Me.gv.Rows
            Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)

            For Each auth As String In Me.authList

                Dim chkAuth As CheckBox = TryCast(row.FindControl("chk" + auth), CheckBox)
                Dim cellIndex = row.Cells.GetCellIndex(chkAuth.Parent)
                Dim chkAll As CheckBox = TryCast(Me.gv.HeaderRow.Cells(cellIndex).Controls(1), CheckBox)

                authDefinitions.DefaultView.RowFilter = String.Format("ProgramID = '{0}' and AuthName = '{1}' ", key("ProgramID"), auth)

                If authDefinitions.DefaultView.Count = 0 Then
                    chkAuth.Visible = False
                    chkAuth.Checked = False
                Else
                    If authDefinitions.DefaultView(0)("Description") IsNot DBNull.Value Then
                        chkAuth.ToolTip = authDefinitions.DefaultView(0)("Description")
                    End If                    
                End If
            Next
        Next


        '
        '
        '
        sql = New MyStringBuilder
        sql.AppendFormat("select ro.*, r.RoleName from RoleProgramMapping ro ")
        sql.AppendFormat("inner join Role r on ro.RoleID = r.RoleID ")
        'sql.AppendFormat("inner join ProgramAuthDefinition pad on ro.ProgramID = pad.ProgramID and ro.AuthName = pad.AuthName ")
        sql.AppendFormat("where r.RoleID = '{0}' ", Me.RoleID)

        Dim mappings As Data.DataTable = dat.GetData(sql.ToString, Nothing, Data.CommandType.Text, "dt").Tables(0)

        For Each row As GridViewRow In Me.gv.Rows
            Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)

            For Each auth As String In Me.authList

                Dim chkAuth As CheckBox = TryCast(row.FindControl("chk" + auth), CheckBox)
                Dim cellIndex = row.Cells.GetCellIndex(chkAuth.Parent)
                Dim chkAll As CheckBox = TryCast(Me.gv.HeaderRow.Cells(cellIndex).Controls(1), CheckBox)

                mappings.DefaultView.RowFilter = String.Format("ProgramID = '{0}' and AuthName = '{1}' ", key("ProgramID"), auth)

                If mappings.DefaultView.Count > 0 Then
                    chkAuth.Checked = True
                Else
                    chkAuth.Checked = False
                End If
            Next
        Next

        '判斷全選選項是否啟用，或打勾
        For Each auth As String In authList

            If parent = Me.RoleID Then ' System 的 parent 仍為 System
                sql.Length = 0
                sql.AppendFormat("select isnull(count(*),0) from ProtectedProgram p ")
                sql.AppendFormat("where p.Active = 'Y' ")

                If Me.ddlProgramGroup.SelectedValue <> "" Then
                    sql.AppendFormat("and p.Parent = {0} ", Me.ddlProgramGroup.SelectedValue)
                End If
            Else
                sql.Length = 0
                sql.AppendFormat("select isnull(count(*),0) from RoleProgramMapping rp ")
                sql.AppendFormat("inner join Program p on rp.ProgramID = p.ProgramID ")
                sql.AppendFormat("where rp.AuthName='{0}' ", auth)
                sql.AppendFormat("and rp.RoleID = {0} ", parent)

                If Me.ddlProgramGroup.SelectedValue <> "" Then
                    sql.AppendFormat("and p.Parent = {0} ", Me.ddlProgramGroup.SelectedValue)
                End If
            End If

            Dim parentCount As Integer = dat.GetData(sql).Rows(0)(0)

            sql.Length = 0
            sql.AppendFormat("select isnull(count(*),0) from RoleProgramMapping rp ")
            sql.AppendFormat("inner join ProtectedProgram p on rp.ProgramID = p.ProgramID ")
            sql.AppendFormat("where rp.AuthName='{0}' ", auth)
            sql.AppendFormat("and rp.RoleID = {0} ", Me.RoleID)
            sql.AppendFormat("and p.Active = 'Y' ")
            If Me.ddlProgramGroup.SelectedValue <> "" Then
                sql.AppendFormat("and p.Parent = {0} ", Me.ddlProgramGroup.SelectedValue)
            End If

            Dim childCount As Integer = dat.GetData(sql).Rows(0)(0)

            Dim chkAll As CheckBox = TryCast(Me.gv.HeaderRow.FindControl("chkAll" + auth), CheckBox)

            If childCount < parentCount OrElse parentCount = 0 Then
                chkAll.Checked = False
            End If
        Next
    End Sub

    Private Function AddRoleAuthMapping(ByVal chkAuth As CheckBox) As Boolean
        Dim sql As New System.Text.StringBuilder
        Dim dat As New clsData

        Using scope As New Transactions.TransactionScope

            'sql.Length = 0
            'sql.AppendFormat("delete RoleProgramMapping ")
            'sql.AppendFormat("where RoleID = '{0}' and ColumnName = '' ", Me.RoleID)

            'dat.AccData(sql.ToString, Nothing, Data.CommandType.Text)

            'For Each row As GridViewRow In Me.gv.Rows
            Dim row As GridViewRow = TryCast(chkAuth.NamingContainer, GridViewRow)
            Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)

            'For Each auth As String In Me.authList
            'Dim chkAuth As CheckBox = TryCast(row.FindControl("chk" + auth), CheckBox)

            Dim auth As String = Me.FindAuth(chkAuth.ID)

            ' chk 為顯示才需新增此權限
            If chkAuth.Checked = True And chkAuth.Enabled = True Then

                sql.Length = 0
                sql.AppendFormat("insert RoleProgramMapping (RoleID,ProgramID,AuthName) select ")
                sql.AppendFormat(" '{0}' ", Me.RoleID)
                sql.AppendFormat(",'{0}' ", key("ProgramID"))
                sql.AppendFormat(",'{0}' ", auth)
                sql.AppendFormat("where not exists (Select * from RoleProgramMapping ")
                sql.AppendFormat("where RoleID='{0}' ", Me.RoleID)
                sql.AppendFormat("and ProgramID='{0}') ", key("ProgramID"))
                dat.AccData(sql.ToString, Nothing, Data.CommandType.Text)

                Dim parentProgramID As Nullable(Of Integer) = clsAuth.GetParentProgramID(key("ProgramID"))

                If parentProgramID.HasValue = True Then
                    Me.UpdateProgramGroupAuth(parentProgramID)
                End If

            Else
                sql.Length = 0
                sql.AppendFormat("delete RoleProgramMapping ")
                sql.AppendFormat("where RoleID = '{0}' ", Me.RoleID)
                sql.AppendFormat("and ProgramID = '{0}' ", key("ProgramID"))
                sql.AppendFormat("and AuthName = '{0}' ", auth)
                dat.AccData(sql.ToString, Nothing, Data.CommandType.Text)

                Dim parentProgramID As Nullable(Of Integer) = clsAuth.GetParentProgramID(key("ProgramID"))

                If parentProgramID.HasValue = True Then
                    Me.UpdateProgramGroupAuth(parentProgramID)
                End If

            End If
            'Next

            'Next

            scope.Complete()
        End Using

        clsAuth.RebuildRoleProgramMapping()

        Return True
    End Function

    Private Function AddAllRoleAuthMapping(ByVal chkAuth As CheckBox) As Boolean
        Dim sql As New System.Text.StringBuilder
        Dim dat As New clsData

        Dim auth As String = Me.FindAuth(chkAuth.ID)

        Using scope As New Transactions.TransactionScope

            sql.Length = 0
            sql.AppendFormat("delete RoleProgramMapping ")
            sql.AppendFormat("where RoleID = '{0}' ", Me.RoleID)
            sql.AppendFormat("and AuthName = '{0}' ", auth)
            dat.AccData(sql.ToString, Nothing, Data.CommandType.Text)

            'For Each row As GridViewRow In Me.gv.Rows
            'Dim key As DataKey = Me.gv.DataKeys(row.RowIndex)

            If chkAuth.Checked Then
                sql.Length = 0
                sql.AppendFormat("insert RoleProgramMapping (RoleID,ProgramID,AuthName) select ")
                sql.AppendFormat(" '{0}' ", Me.RoleID)
                sql.AppendFormat(",{0} ", "ProgramID")
                sql.AppendFormat(",'{0}' ", auth)

                Dim parent As Integer = clsAuth.GetParentRoleID(Me.RoleID)

                If Me.RoleID = parent Then
                    sql.AppendFormat("from Program ")
                    sql.AppendFormat("where Active = 'Y' ")
                Else
                    sql.AppendFormat("from RoleProgramMappingView rp ")
                    sql.AppendFormat("where rp.RoleID = {0} ", parent)
                    sql.AppendFormat("and rp.AuthName = '{0}' ", auth)
                End If

                dat.AccData(sql.ToString, Nothing, Data.CommandType.Text)

            End If

            'Next

            scope.Complete()
        End Using

        Return True
    End Function

    Private Sub UpdateProgramGroupAuth(ByVal programID As Integer)
        Dim sql As New MyStringBuilder
        Dim dat As New clsData

        '看此群組下之選單是否有設定權限
        sql.Length = 0
        sql.AppendFormat("select top 1 rp.* from RoleProgramMapping rp ")
        sql.AppendFormat("inner join Program p on rp.ProgramID = p.ProgramID ")
        sql.AppendFormat("where rp.RoleID = {0} ", Me.RoleID)
        sql.AppendFormat("and p.Parent = {0} ", programID)

        If dat.GetData(sql).Rows.Count = 0 Then
            sql.Length = 0
            sql.AppendFormat("delete RoleProgramMapping where ")
            sql.AppendFormat("RoleID = {0} ", Me.RoleID)
            sql.AppendFormat("and ProgramID = {0} ", programID)
            dat.AccData(sql)

        Else
            sql.Length = 0
            sql.AppendFormat("delete RoleProgramMapping where ")
            sql.AppendFormat("RoleID = {0} ", Me.RoleID)
            sql.AppendFormat("and ProgramID = {0} ", programID)
            dat.AccData(sql)

            sql.Length = 0
            sql.AppendFormat("insert RoleProgramMapping (RoleID,ProgramID,AuthName) select ")
            sql.AppendFormat(" '{0}' ", Me.RoleID)
            sql.AppendFormat(",'{0}' ", programID)
            sql.AppendFormat(",'{0}' ", "Admin")

            dat.AccData(sql)
        End If
    End Sub

    Public Property RoleID() As String
        Get
            Return ViewState("RoleID")
        End Get
        Set(ByVal value As String)
            ViewState("RoleID") = value
        End Set
    End Property

    Public Event Loaded(ByVal source As Object, ByVal e As EventArgs)

End Class